package com.sikaryofficial.backend.manager;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.google.common.collect.Lists;
import com.sikaryofficial.backend.constant.ActivityConstant;
import com.sikaryofficial.backend.constant.ActivityTypeEnum;
import com.sikaryofficial.backend.constant.PrizeTypeEnum;
import com.sikaryofficial.backend.domain.dto.req.productactivity.ActivityPrizeRelationItem;
import com.sikaryofficial.backend.domain.dto.req.productactivity.ActivityPrizeRelationReq;
import com.sikaryofficial.backend.domain.dto.resp.productactivity.ActivityPrizeRelationDTO;
import com.sikaryofficial.backend.domain.entity.Activity;
import com.sikaryofficial.backend.domain.entity.ActivityPrizeRelation;
import com.sikaryofficial.backend.domain.entity.Prize;
import com.sikaryofficial.backend.domain.mapping.ActivityPrizeRelationMapping;
import com.sikaryofficial.backend.domain.mapping.PrizeMapping;
import com.sikaryofficial.backend.service.IActivityPrizeRelationService;
import com.sikaryofficial.backend.service.IActivityService;
import com.sikaryofficial.backend.service.IPrizeService;
import com.sikaryofficial.common.core.exception.ServiceException;
import com.sikaryofficial.common.security.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author : qinjinyuan
 * @desc : 活动奖项设置
 * @date : 2023/10/30 15:39
 */
@Service
@Slf4j
@SuppressWarnings(value = "unchecked")
public class ActivitySettingManager {
    @Autowired
    private IActivityService activityService;
    @Autowired
    private IActivityPrizeRelationService relationService;
    @Autowired
    private IPrizeService prizeService;
    /**
     * 活动奖项设置-保存或更新
     *
     * @param activityId 活动ID
     * @param req        请求对象
     * @return
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void saveOrUpdate(Long activityId, ActivityPrizeRelationReq req) {
        // 上架状态的活动不能进行操作，
        Activity activity = activityService.getOne(new LambdaQueryWrapper<Activity>()
                .eq(Activity::getActivityId, activityId)
                .eq(Activity::getDeletedVersion, 0)
        );
        if (Objects.nonNull(activity) && Objects.nonNull(activity.getHasEffect())
                && Objects.equals(ActivityConstant.EFFECT_YES, activity.getHasEffect())) {
            throw new ServiceException("上架状态的活动不能进行操作,请先下架");
        }
        ActivityTypeEnum activityTypeEnum = ActivityTypeEnum.getNameByCode(activity.getActivityType());
        // 奖项数量校验
        validItemNum(activityId, req, activityTypeEnum);
        List<ActivityPrizeRelationItem> validItems = req.getItems();
        int count = 1;
        for (ActivityPrizeRelationItem relationItem : validItems) {
            try {
                // 活动类型和奖项数量校验
                validateActivityTypeAndPrizeCount(activityTypeEnum, relationItem);
                // 奖项库存校验
                validateStock(relationItem);
                // 活动校验
                verifyActivity(activityId);
                // 保存活动奖项关系数据
                relationItem.setActivityId(activityId);
                // 赋值sort字段
                relationItem.setSort(count++);
            } catch (Exception e) {
                log.error("保存或更新活动奖项失败", e);
                throw e;
            }
        }
        List<ActivityPrizeRelation> relationsDB = relationService.list(new LambdaQueryWrapper<ActivityPrizeRelation>()
                .eq(ActivityPrizeRelation::getActivityId, activityId)
                .eq(ActivityPrizeRelation::getDeletedVersion, 0L)
        );
        // items 与 relationsDB 进行对比，判定哪些是新增，哪些是更新，哪些是删除
        compareAndUpdate(validItems, relationsDB);
    }

    private void validItemNum(Long activityId, ActivityPrizeRelationReq req, ActivityTypeEnum activityTypeEnum) {
        if (Objects.isNull(activityTypeEnum)) {
            log.error("活动类型错误, activityId: {}", activityId);
            throw new ServiceException("活动类型错误");
        }
        // 原来的活动，只支持一个奖项，并且奖品数量只能是1，且是实体奖项
        boolean activityTypeFlag = activityTypeEnum == ActivityTypeEnum.PURCHASE
                || activityTypeEnum == ActivityTypeEnum.PURCHASE_ACTIVATE_NOW;
        if (activityTypeFlag && req.getItems().size() > 1) {
            log.error("活动类型错误, activityId: {}", activityId);
            throw new ServiceException("不能新增活动奖项，该活动类型:" + activityTypeEnum.getDesc()
                    + " 仅支持最多 " + ActivityConstant.ACTIVITY_PRIZE_RELATION_MAX_COUNT + " 个活动奖项。");
        }
    }

    public void compareAndUpdate(List<ActivityPrizeRelationItem> validItems, List<ActivityPrizeRelation> relationsDB) {
        // Step 1: Create a map from relationsDB with activityPrizeId as key
        Map<Long, ActivityPrizeRelation> existingRelations = relationsDB.stream()
                .collect(Collectors.toMap(ActivityPrizeRelation::getActivityPrizeId, Function.identity(), (k1, k2) -> k1));

        // Step 2: Update or mark for insert based on validItems
        for (ActivityPrizeRelationItem item : validItems) {
            if (existingRelations.containsKey(item.getActivityPrizeId())) {
                // Update existing record
                updateRelation(item);
            } else {
                // Mark for insert
                saveOrUpdateRelation(item);
            }
        }

        // Step 3: Detect deletions
        List<Long> existingIds = existingRelations.keySet().stream()
                .filter(id -> validItems.stream().noneMatch(item -> id.equals(item.getActivityPrizeId())))
                .collect(Collectors.toList());

        // Mark these IDs for deletion
        existingIds.forEach(this::deleteRelation);
    }

    private void updateRelation(ActivityPrizeRelationItem itemReq) {
        // Update logic here
        ActivityPrizeRelation relation = ActivityPrizeRelationMapping.INSTANCE.coverReqToEntity(itemReq);
        // Save or update logic here
        relation.setUpdatedBy(SecurityUtils.getUserId());
        relation.setUpdatedTime(new Date());
        relationService.saveOrUpdate(relation);
    }

    private void saveOrUpdateRelation(ActivityPrizeRelationItem relationItem) {
        ActivityPrizeRelation relation = ActivityPrizeRelationMapping.INSTANCE.coverReqToEntity(relationItem);
        // Save or update logic here
        relation.setActivityPrizeId(IdWorker.getId());
        relation.setCreatedBy(SecurityUtils.getUserId());
        relation.setCreatedTime(new Date());
        relationService.save(relation);
    }

    private void deleteRelation(Long id) {
        // Delete logic here
        relationService.update(new LambdaUpdateWrapper<ActivityPrizeRelation>()
                .setSql(" deleted_version = activity_prize_id ")
                .eq(ActivityPrizeRelation::getActivityPrizeId, id)
                .eq(ActivityPrizeRelation::getDeletedVersion, 0L)
        );
    }

    private void validateActivityTypeAndPrizeCount(ActivityTypeEnum activityTypeEnum, ActivityPrizeRelationItem req) {
        // 原来的活动，只支持一个奖项，并且奖品数量只能是1，且是实体奖项
        boolean activityTypeFlag = activityTypeEnum == ActivityTypeEnum.PURCHASE
                || activityTypeEnum == ActivityTypeEnum.PURCHASE_ACTIVATE_NOW;
        if (activityTypeFlag && Objects.isNull(req.getActivityPrizeId())) { // 新增奖项
            Prize prize = prizeService.getOne(new LambdaQueryWrapper<Prize>()
                    .eq(Prize::getPrizeId, req.getPrizeId())
                    .eq(Prize::getDeletedVersion, 0L)
            );
            if (Objects.isNull(prize)) {
                log.error("礼品不存在");
                throw new ServiceException("礼品不存在");
            }
            if (!Objects.equals(prize.getPrizeType(), PrizeTypeEnum.PHYSICAL.getCode())) {
                log.error("礼品类型不支持");
                throw new ServiceException("该活动类型:" + activityTypeEnum.getDesc()
                        + " 仅支持" + PrizeTypeEnum.PHYSICAL.getName() + " 奖项。");
            }
        }
    }

    private void validateStock(ActivityPrizeRelationItem req) {
        // 库存 只能等于 -1 或者大于 0
        boolean stockFlag = req.getStock() >= -1;
        if (Objects.isNull(req.getStock()) || !stockFlag) {
            throw new ServiceException("奖品选项：" + req.getLabelName() + " 库存只能大于等于 -1");
        }
    }

    /**
     * 活动奖项设置-删除
     *
     * @param activityId      活动ID
     * @param activityPrizeId 活动奖项ID
     */
    public void remove(Long activityId, Long activityPrizeId) {
        verifyActivity(activityId);
        relationService.update(new LambdaUpdateWrapper<ActivityPrizeRelation>()
                .setSql(" deleted_version = activity_prize_id ")
                .set(ActivityPrizeRelation::getUpdatedBy, SecurityUtils.getUserId())
                .set(ActivityPrizeRelation::getUpdatedTime, new Date())
                .eq(ActivityPrizeRelation::getActivityId, activityId)
                .eq(ActivityPrizeRelation::getActivityPrizeId, activityPrizeId)
                .eq(ActivityPrizeRelation::getDeletedVersion, 0L)
        );
    }

    /**
     * 验证活动
     *
     * @param activityId 活动ID
     */
    private void verifyActivity(Long activityId) {
        // 如果当前活动已上架，不能删除
        Activity activity = activityService.getOne(new LambdaQueryWrapper<Activity>()
                .select(Activity::getActivityId, Activity::getHasEffect)
                .eq(Activity::getActivityId, activityId)
                .eq(Activity::getDeletedVersion, 0L)
        );
        if (Objects.nonNull(activity) && Objects.equals(activity.getHasEffect(), ActivityConstant.EFFECT_YES)) {
            throw new ServiceException("活动已上架，不能操作; 可先下架活动，再进行处理");
        }
    }

    /**
     * 活动奖项设置-详情
     *
     * @param activityId      活动ID
     * @param activityPrizeId 活动奖项设置ID
     * @return 活动奖项设置对象
     */
    public ActivityPrizeRelationDTO detail(Long activityId, Long activityPrizeId) {
        // 查询关系数据
        ActivityPrizeRelation relation = relationService.getOne(new LambdaQueryWrapper<ActivityPrizeRelation>()
                .eq(ActivityPrizeRelation::getActivityId, activityId)
                .eq(ActivityPrizeRelation::getActivityPrizeId, activityPrizeId)
                .eq(ActivityPrizeRelation::getDeletedVersion, 0L)
        );
        if (Objects.isNull(relation)) {
            return null;
        }
        ActivityPrizeRelationDTO relationDTO = ActivityPrizeRelationMapping.INSTANCE.coverToDTO(relation);
        // 查询奖品数据
        if (Objects.isNull(relationDTO)) {
            return null;
        }
        Prize prize = prizeService.getPrizeListById(relationDTO.getPrizeId());
        // 填充奖品信息
        fillPrizeInfo(relationDTO, prize);
        return relationDTO;
    }

    /**
     * 查询当前活动的配置的礼品ID列表
     *
     * @param activityId
     * @return
     */
    public List<Long> getPrizeIdByActivityId(Long activityId) {
        // 查询关系数据
        List<ActivityPrizeRelation> relations = relationService.list(new LambdaQueryWrapper<ActivityPrizeRelation>()
                .select(ActivityPrizeRelation::getPrizeId)
                .eq(ActivityPrizeRelation::getActivityId, activityId)
                .eq(ActivityPrizeRelation::getDeletedVersion, 0L)
        );
        if (CollUtil.isEmpty(relations)) {
            return Lists.newArrayList();
        }
        return relations.stream().map(ActivityPrizeRelation::getPrizeId).collect(Collectors.toList());
    }

    /**
     * 活动奖项设置-列表
     *
     * @param activityId 活动ID
     * @return 奖项设置列表
     */
    public List<ActivityPrizeRelationDTO> itemList(Long activityId) {
        // 查询关系数据
        List<ActivityPrizeRelation> relations = relationService.list(new LambdaQueryWrapper<ActivityPrizeRelation>()
                .eq(ActivityPrizeRelation::getActivityId, activityId)
                .eq(ActivityPrizeRelation::getDeletedVersion, 0L)
                .orderByAsc(ActivityPrizeRelation::getSort, ActivityPrizeRelation::getActivityPrizeId)
        );
        if (CollUtil.isEmpty(relations)) {
            return Lists.newArrayList();
        }
        List<ActivityPrizeRelationDTO> relationDTOs = ActivityPrizeRelationMapping.INSTANCE.coverToDTOs(relations);
        // 查询奖品数据
        Set<Long> prizeIdSet = relationDTOs.stream().map(ActivityPrizeRelationDTO::getPrizeId).collect(Collectors.toSet());
        if (CollUtil.isEmpty(prizeIdSet)) {
            return relationDTOs;
        }
        Map<Long, Prize> prizeMap = prizeService.getPrizeListByIds(new ArrayList<>(prizeIdSet));
        // 填充相关数据
        for (ActivityPrizeRelationDTO relation : relationDTOs) {
            Prize prize = MapUtils.getObject(prizeMap, relation.getPrizeId());
            // 填充奖品信息
            fillPrizeInfo(relation, prize);
        }
        return relationDTOs;
    }

    /**
     * 填充奖品信息
     *
     * @param relation 活动奖项设置对象
     * @param prize    礼品对象
     */
    private void fillPrizeInfo(ActivityPrizeRelationDTO relation, Prize prize) {
        if (Objects.isNull(relation) || Objects.isNull(prize)) {
            return;
        }
        relation.setPrizeInfo(PrizeMapping.INSTANCE.coverToDTO(prize));
    }
}
